package info.xmlprint.ui.innerlink;

import info.xmlprint.core.innerlink.InnerLink;
import info.xmlprint.core.innerlink.InnerLinkGroup;
import info.xmlprint.core.project.PrintProject;
import info.xmlprint.ui.message.GuiMessages;
import info.xmlprint.ui.widgets.IObserverControl;
import info.xmlprint.ui.widgets.ISetupComposite;
import info.xmlprint.util.FileUtil;
import info.xmlprint.util.ResizeColumns;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;

public class InnerLinkSetup extends Composite implements IObserverControl,
		ISetupComposite {

	private class LocalContentProvider implements ITreeContentProvider {

		@Override
		public void dispose() {
		}

		@Override
		public Object[] getChildren(Object parentElement) {
			return null;
		}

		@Override
		public Object[] getElements(Object list) {
			if (list instanceof InnerLinkGroup) {
				return ((InnerLinkGroup) list).getItems().toArray();
			}
			return null;
		}

		@Override
		public Object getParent(Object element) {
			return null;
		}

		@Override
		public boolean hasChildren(Object element) {
			return false;
		}

		@Override
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
	}

	private class LocalLabelProvider implements ITableLabelProvider {

		@Override
		public void addListener(ILabelProviderListener listener) {
		}

		@Override
		public void dispose() {
		}

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object obj, int index) {
			if (obj instanceof InnerLink) {
				InnerLink link = (InnerLink) obj;
				// col name
				if (index == 0) {
					return link.getValueOf("source-element") + " : "
							+ link.getValueOf("source-attribut");
				} else {
					return link.getValueOf("target-element") + " : "
							+ link.getValueOf("target-attribut");
				}
			}
			return null;
		}

		@Override
		public boolean isLabelProperty(Object element, String property) {
			return false;
		}

		@Override
		public void removeListener(ILabelProviderListener listener) {
		}
	}

	private PrintProject printProject;

	private InnerLinkComposite editComposite;

	private Shell editShell;

	// private InnerLinkExceptionsComposite editExceptionsComposite;

	private TreeViewer treeViewer;

	public InnerLinkSetup(Composite parent, int style) {
		super(parent, style);
		this.setLayout(new FillLayout());
		this.addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(DisposeEvent e) {
				treeViewer.getControl().dispose();
				treeViewer = null;
				if (editShell != null && !editShell.isDisposed()) {
					editShell.dispose();
				}
			}
		});

		initGui();
	}

	private void delItemAction(InnerLink field) {
		printProject.getInnerLinkGroup().remove(field);
		updateControl();
	}

	private void initGui() {
		treeViewer = new TreeViewer(this, SWT.FULL_SELECTION | SWT.MULTI);
		final Tree tree = treeViewer.getTree();
		tree.setHeaderVisible(true);
		tree.setLinesVisible(true);
		TableLayout tableLayout = new TableLayout();
		tree.setLayout(tableLayout);

		TreeColumn nameCol = new TreeColumn(tree, SWT.NONE);
		nameCol.setText("Source");// TODO: Text from gui.properties

		TreeColumn titleCol = new TreeColumn(tree, SWT.NONE);
		titleCol.setText("Target");// TODO: Text from gui.properties

		treeViewer.setContentProvider(new LocalContentProvider() {
		});
		treeViewer.setLabelProvider(new LocalLabelProvider() {
		});

		tree.addListener(SWT.MouseDoubleClick, new Listener() {
			@Override
			public void handleEvent(Event e) {
				TreeItem treeItem = tree.getItem(new Point(e.x, e.y));
				if (treeItem != null) {
					InnerLink selectedField = (InnerLink) treeItem.getData();
					openFieldEditShell(selectedField);
				} else
					openFieldEditShell(null);
			}
		});

		tree.addListener(SWT.MenuDetect, new Listener() {
			@Override
			public void handleEvent(Event event) {
				final InnerLink selectedItem;

				if (tree.getSelection() == null || tree.getSelectionCount() < 1) {
					selectedItem = null;
				} else {
					TreeItem ti = tree.getSelection()[0];
					selectedItem = (InnerLink) ti.getData();
				}

				Menu menu = new Menu(tree.getShell(), SWT.POP_UP);

				MenuItem editItem = new MenuItem(menu, SWT.PUSH);
				editItem.setText(GuiMessages.General_Gui_Edit);
				editItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						openFieldEditShell(selectedItem);
					}
				});
				if (selectedItem == null) {
					editItem.setEnabled(false);
				}

				MenuItem delItem = new MenuItem(menu, SWT.PUSH);
				delItem.setText(GuiMessages.General_Gui_Delete);
				delItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {

						// TODO: Text from gui.properties
						if (MessageDialog.openConfirm(null, "",
								"Sind Sie sicher?")) { // TODO
							delItemAction(selectedItem);
						}
					}
				});

				if (selectedItem == null) {
					delItem.setEnabled(false);
				}

				new MenuItem(menu, SWT.SEPARATOR);

				MenuItem addItem = new MenuItem(menu, SWT.PUSH);
				addItem.setText(GuiMessages.General_Gui_Add);
				addItem.addSelectionListener(new SelectionAdapter() {
					@Override
					public void widgetSelected(SelectionEvent e) {
						openFieldEditShell(null);
					}
				});
				menu.setVisible(true);
			}
		});

		this.addControlListener(new ResizeColumns(this, tree));
	}

	/*
	 * Eistellungsfenster fuer ausgewaehltes Feld
	 */
	private void openFieldEditShell(InnerLink toEdit) {
		if (editShell == null) {
			editShell = new Shell(this.getDisplay(), SWT.CLOSE | SWT.MIN
					| SWT.APPLICATION_MODAL | SWT.RESIZE | SWT.MAX);
			// TODO: Text from gui.properties
			editShell.setText("Inner link definition");
			FileUtil.shellSetCenter(editShell);
			editShell.setLayout(new GridLayout());
			editShell.addListener(SWT.Close, new Listener() {
				public void handleEvent(Event event) {
					editShell.setVisible(false);
					event.doit = false;
				}
			});
			editComposite = new InnerLinkComposite(editShell, SWT.NONE);
			editComposite.setLayoutData(new GridData(GridData.FILL_BOTH));
			editComposite.registerObserver(this); 
			editShell.setSize(800, 600);
			editShell.layout();
			// editShell.pack();
		}
		editShell.open();
		editComposite.setPrintProject(printProject);
		editComposite.setInput(toEdit);
	}

	@Override
	public void setPrintProject(PrintProject pProject) {
		printProject = pProject;
		treeViewer.setInput(pProject.getInnerLinkGroup());
	}

	@Override
	public void updateControl() {
		treeViewer.refresh();
	}

}
